home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
LIBIP
/
SGL_STAT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
8KB
|
303 lines
/*
* sgl_stat.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/*
* SGL_STATS
*
* determine geometrical properties of a cluster of linear segments
* in a given SGL
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include "ip.h"
#define TWO 2
#define THREE 3
#define DIM TWO
#define SN_LOLIM 0.002 /* lower limit: 1/512 */
#define CS_LOLIM 0.002
#undef DEBUG
/*
* nematic_op()
* DESCRIPTION:
* nematic_op evaluates nematic order parameter S = <3*cos_th*cos_th - 1>/2 (3d)
* or S = <2*cos_th*cos_th - 1> (2d) for the ensemble of clusters (SGLs);
* ARGUMENTS:
* n_sgl(int) number of segment group lists
* n_segm(int) number of clusters
* dirns(float *) cluster orientations
* RETURN VALUE:
* total angular bend for the contour
* COMMENTS:
* note: *dirns is a ptr to an array containing the slopes of the
** linear segments in a given SGL
** loop over the n_sgl <= n_segm of non_empty SGLs only:
** *dirns is expected to be initialized to 999.0; this
** serves to identify unused elements;
** (see also: slope() in xsgll.c);
** for each SGL (cluster) the array *dirns holds the average slope
** of the segments in that cluster; since there is no preferred
** orientation of segments, corresponding directions are
** defined to within modulo PI; it is with respect to the
** the average direction that the order parameter S is
** evaluated
*/
float
nematic_op (int n_sgl, int n_segm, float *dirns)
{
float slpi, av_slope;
double sn_2th, cs_2th, th;
double cs2_th, tg_th, s;
float order_parm;
int i;
#ifdef DEBUG
printf ("\n...nematic order parameter for %d clusters:\n", n_segm);
printf ("...cluster orientations:\n");
for (i = 0; i < n_segm; i++) {
if (*(dirns + i) < 999.0)
printf (" SGL<%d>: %6.2f\n", i, *(dirns + i));
}
#endif
/* determine preferred direction */
sn_2th = cs_2th = 0.0;
for (i = 0; i < n_segm; i++) {
if ((slpi = *(dirns + i)) < 999.0) { /* valid entry for slope */
cs_2th += (double) ((1.0 - slpi * slpi) / (1.0 + slpi * slpi));
sn_2th += (double) (2.0 * slpi / (1.0 + slpi * slpi));
}
}
sn_2th /= (double) n_sgl;
cs_2th /= (double) n_sgl;
if (fabs (cs_2th) < CS_LOLIM)
cs_2th = SIGN (cs_2th) * CS_LOLIM;
th = 0.5 * atan2 (sn_2th, cs_2th);
if (fabs (sn_2th) < SN_LOLIM) {
printf ("\n...no preferred direction!\n");
th = 0.0;
}
#ifdef DEBUG
printf ("...sn_2th = %6.4lf, cs_2th = %6.4lf, th = %8.4lf deg\n",
sn_2th, cs_2th, th);
#endif
av_slope = (float) tan (th);
/* evaluate order parameter */
order_parm = (float) 0.0;
for (i = 0; i < n_segm; i++) { /* deviations from av slope */
if ((slpi = *(dirns + i)) < 999.0) {
if (slpi * av_slope == -1.0)
tg_th = 512.0; /* perp orientation */
else
tg_th = (slpi - av_slope) / (1.0 + slpi * av_slope);
cs2_th = 1.0 / (1.0 + tg_th * tg_th);
if (DIM == THREE)
s = 0.5 * (3.0 * cs2_th - 1.0);
if (DIM == TWO)
s = (2.0 * cs2_th - 1.0);
order_parm += (float) s;
}
}
order_parm /= (float) n_sgl;
return (order_parm);
}
/*
* eccentr()
* DESCRIPTION:
* eccentr evaluates aspect ratio of a given cluster (SGL) of segments
* as the ratio of the maximum longitudinal and transverse dimensions,
* the latter being identical to the maximum segment length in the SGL
* ARGUMENTS:
* segm(struct Segm *) pointer to segment structure (see sgl_stat.h)
* list(struct linklist *) pointer to linked list structure (see lldef.h)
* len(float *) length of SGL
* width(float *) width of SGL
* RETURN VALUE:
* aspect ratio of SGL (length/width)
*/
float
eccentr (struct Segm *segm, struct linklist *list, float *len, float *width)
{
struct Segmtype *cSegm;
float del_x, del_y;
float d_min, d_max;
float csegm_len, max_segm_len;
/* length */
llhead (list);
cSegm = (struct Segmtype *) list->clp->item;
d_min = cSegm->dij;
lltail (list);
cSegm = (struct Segmtype *) list->clp->item;
d_max = cSegm->dij;
*len = d_max - d_min;
/* width */
max_segm_len = (float) 0.0;
llhead (list);
do {
cSegm = (struct Segmtype *) list->clp->item;
del_x = (float) ((segm + cSegm->segm_ind)->ptF.x - (segm + cSegm->segm_ind)->ptO.x);
del_y = (float) ((segm + cSegm->segm_ind)->ptF.y - (segm + cSegm->segm_ind)->ptO.y);
csegm_len = (float) sqrt (del_x * del_x + del_y * del_y);
if (csegm_len > max_segm_len)
max_segm_len = csegm_len;
} while (llnext (list) == True);
*width = max_segm_len;
return (*len / (*width));
}
/*
* find_ex_hist()
* DESCRIPTION:
* find_ex_hist constructs a histogram of SGL (cluster) aspect ratios
* (ex refers to eccentricity for which the aspect ratio is a crude measure)
* ARGUMENTS:
* n_segm(int) number of SGLs to calculate histogram for
* asp_ratio(float *) array of aspect ratios for SGLs
* ex_hist(int *) output histogram
* bw(double) bin width of the histogram
* ar_base(double) minimum aspect ratio (base)
* RETURN VALUE:
* none
*/
void
find_ex_hist (int n_segm, float *asp_ratio, int *ex_hist, double bw, double ar_base)
{
int i, ibin;
for (i = 0; i < n_segm; i++) {
if (*(asp_ratio + i) != 0.0) {
ibin = 1;
while (*(asp_ratio + i) > ar_base + ibin * bw)
ibin++;
*(ex_hist + ibin - 1) += 1;
}
}
}
/*
* find_lsz_hist()
* DESCRIPTION:
* find_lsz_hist constructs a histogram of SGL (cluster) longitudinal sizes (no of segm)
* ARGUMENTS:
* n_segm(int) number of SGLs to calculate histogram for
* lsize(int *) array of longitudinal for SGLs
* lsz_hist(int *) calculated histogram for SGLs
* nbins(int) currently not used
* lsz_base(int) base of the histogram
* RETURN VALUE:
* none
*/
void
find_lsz_hist (int n_segm, int *lsize, int *lsz_hist, int nbins, int lsz_base)
{
int i, ibin;
for (i = 0; i < n_segm; i++) {
if (*(lsize + i) != 0) {
ibin = 1;
while (*(lsize + i) >= lsz_base + ibin)
ibin++;
*(lsz_hist + ibin - 1) += 1;
}
}
}
/*
* zero_moment()
* DESCRIPTION:
* zero_moment evaluates zero order moment: x_vert and y_vert are assumed to represent
* a closed polygon (last vertex assumed identical with first vertex)
* ARGUMENTS:
* nv(int) number of vertices in polygon
* xv, yv(int *) (x,y) points of vertices
* RETURN VALUE:
* zero order moment of polygon
*/
int
zero_moment (int nv, int *xv, int *yv)
{
register int i;
double xim1, xi, yim1, yi;
double m00, m00_sum;
m00 = m00_sum = 0.0;
for (i = 1; i <= nv; i++) {
xim1 = (double) (*(xv + i - 1));
xi = (double) (*(xv + i));
yim1 = (double) (*(yv + i - 1));
yi = (double) (*(yv + i));
m00_sum = 0.5 * (yi * xim1 - xi * yim1);
m00 += m00_sum;
}
return ((int) fabs (m00));
}
/*
* find_area_hist()
* DESCRIPTION:
* find_area_hist constructs histogram of SGL (cluster) areas
* ARGUMENTS:
* n_segm(int) number of SGLs to calculate histogram for
* area(int *) SGL array of areas
* area_hist(int *) array of histograms filled
* bw(int) bin width of the histogram
* area_base(int) minimum aspect ratio (base)
* RETURN VALUE:
* zero order moment of polygon
*/
void
find_area_hist (int n_segm, int *area, int *area_hist, int bw, int area_base)
{
int i, ibin;
int up_bw;
up_bw = (int) bw + 1;
for (i = 0; i < n_segm; i++) {
if (*(area + i) != 0) {
ibin = 1;
while (*(area + i) > area_base + ibin * up_bw)
ibin++;
*(area_hist + ibin - 1) += 1;
}
}
}